/*
 * TrackFileAssistant
 */
package filesystem;

import filesystem.exceptions.InvalidModelItemException;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import model.*;

/**
 *
 * @author ArieS
 */
public class TrackFileAssistant extends FileAssistantAbstract {

    private static TrackFileAssistant instance;

    private TrackFileAssistant() {
        super("\\MusicLibrary\\tracks", ".trck", "track");
    }

    public static TrackFileAssistant getInstance() {
        if (instance == null) {
            instance = new TrackFileAssistant();
        }
        return instance;
    }

    @Override
    protected Map itemToMap(ModelItem mi) {
        Map map = super.itemToMap(mi);
        Track trck = (Track) mi;
        map.put("artist", trck.getArtist().getId());
        map.put("album", trck.getAlbum().getId());
        map.put("genre", trck.getGenre().getId());
        map.put("length", trck.getLength());
        map.put("size", trck.getSize());
        map.put("version", trck.getVersion());
        return map;
    }

    @Override
    protected ModelItem mapToItem(Map map) {
        ModelItem mi = null;
        try {
            Artist art;
            Album alb;
            Genre gnr;
            int id = Integer.parseInt(map.get("id").toString());
            String name = map.get("name").toString();
            try {
                art = (Artist) Assistants.arFA.getItem(Integer.parseInt(map.get("artist").toString()));
            } catch (NumberFormatException | IOException ex) {
                art = null;
            }
            try {
                alb = (Album) Assistants.alFA.getItem(Integer.parseInt(map.get("album").toString()));
            } catch (NumberFormatException | IOException ex) {
                alb = null;
            }
            try {
                gnr = (Genre) Assistants.gFA.getItem(Integer.parseInt(map.get("genre").toString()));
            } catch (NumberFormatException | IOException ex) {
                gnr = null;
            }
            int len = Integer.parseInt(map.get("length").toString());
            int size = Integer.parseInt(map.get("size").toString());
            mi = new Track(id, name, art, alb, gnr, len, size);
            mi.setVersion(Integer.parseInt(map.get("version").toString()));
        } catch (Exception ex) {
            throw new InvalidModelItemException();
        }
        return mi;
    }

    @Override
    public ArrayList getItems(Map map, ArrayList al) throws IOException {
        ArrayList<Track> restItems = (ArrayList) super.items.clone();
        Pattern pattern;
        Matcher matcher = null;
        Track tmpModelItem;
        int i = 0;
        int j;
        boolean rest;
        Map tmpMap;
        while (i < restItems.size()) {
            rest = true;
            for (Object ob : map.entrySet()) {
                Map.Entry men = (Map.Entry) ob;
                for (Object o : ((Map) men.getValue()).entrySet()) {
                    if (!rest) {
                        break;
                    }
                    Map.Entry me = (Map.Entry) o;
                    if (me.getValue() == null) {
                        continue;
                    }
                    tmpModelItem = (Track) restItems.get(i);
                    switch (String.valueOf(me.getKey()).toLowerCase()) {
                        case "name":
                            pattern = Pattern.compile(String.valueOf(me.getValue()));
                            matcher = pattern.matcher(tmpModelItem.getName().toLowerCase());
                            break;
                        case "length":
                            pattern = Pattern.compile(String.valueOf(me.getValue()));
                            matcher = pattern.matcher(String.valueOf(tmpModelItem.getLength()).toLowerCase());
                            break;
                        case "size":
                            pattern = Pattern.compile(String.valueOf(me.getValue()));
                            matcher = pattern.matcher(String.valueOf(tmpModelItem.getSize()).toLowerCase());
                            break;
                        case "album":
                            ArrayList<Album> albumList = new ArrayList<>();
                            for (Track track : restItems) {
                                albumList.add(track.getAlbum());
                            }
                            tmpMap = new HashMap();
                            tmpMap.put(me.getKey(), me.getValue());
                            albumList = Assistants.alFA.getItems(tmpMap, albumList);

                            rest = false;
                            for (Album album : albumList) {
                                if (restItems.get(i).getAlbum().equals(album)) {
                                    rest = true;
                                }
                            }
                            if (!rest) {
                                restItems.remove(i);
                            } 
                            continue;

                        case "artist":
                            ArrayList<Artist> artistList = new ArrayList<>();
                            for (Track track : restItems) {
                                artistList.add(track.getArtist());
                            }
                            tmpMap = new HashMap();
                            tmpMap.put(me.getKey(), me.getValue());
                            artistList = Assistants.alFA.getItems(tmpMap, artistList);

                            rest = false;
                            for (Artist artist : artistList) {
                                if (restItems.get(i).getArtist().equals(artist)) {
                                    rest = true;
                                }
                            }
                            if (!rest) {
                                restItems.remove(i);
                            }
                            continue;
                        case "genre":
                            ArrayList<Genre> genreList = new ArrayList<>();
                            for (Track track : restItems) {
                                genreList.add(track.getGenre());
                            }
                            tmpMap = new HashMap();
                            tmpMap.put(me.getKey(), me.getValue());
                            genreList = Assistants.alFA.getItems(tmpMap, genreList);

                            rest = false;
                            for (Genre genre : genreList) {
                                if (restItems.get(i).getGenre().equals(genre)) {
                                    rest = true;
                                }
                            }
                            if (!rest) {
                                restItems.remove(i);
                            } 
                            continue;
                        default:
                            throw new InvalidModelItemException();
                    }
                    if (!matcher.matches()) {
                        restItems.remove(i);
                        rest = false;
                    }
                    else {
                        rest = true;
                    }
                }
            }
            if (rest) {
                i++;
            }
        }
        return restItems;
    }
}
